package com.framework.auth.config;

import com.framework.common.exception.Auth2ResponseExceptionTranslator;
import com.framework.common.exception.CustomAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

/**
 * 认证服务器配置
 * @author zhoubb
 * @version V1.0
 * @Date 2020/4/12 15:12
 * @since JDK 1.8
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Qualifier("userDetailsService")
    @Autowired
    private UserDetailsService userDetailsService;


    //令牌存储
    @Bean
    public TokenStore tokenStore() {
        //return new InMemoryTokenStore();
        return new RedisTokenStore(redisConnectionFactory);
    }

    // redis连接工厂
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    // 认证管理器
    @Autowired
    private AuthenticationManager authenticationManager;

//    @Autowired(required = false)
//    private JwtAccessTokenConverter jwtAccessTokenConverter;
//
//    @Autowired(required = false)
//    private TokenEnhancer jwtTokenEnhancer;


    @Bean
    public DefaultTokenServices defaultTokenServices() throws Exception {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
//		defaultTokenServices.setAuthenticationManager(authenticationManager);
        defaultTokenServices.setTokenStore(tokenStore());
//		defaultTokenServices.setClientDetailsService(new InMemoryClientDetailsService());

        // access token有效期2个小时
        defaultTokenServices.setAccessTokenValiditySeconds(21600);
        // refresh token有效期30天
        defaultTokenServices.setRefreshTokenValiditySeconds(604800);
        // 支持使用refresh token刷新access token
        defaultTokenServices.setSupportRefreshToken(true);
        // 允许重复使用refresh token
        defaultTokenServices.setReuseRefreshToken(true);
        return defaultTokenServices;
    }

    /**
     * client存储方式
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient("my-trusted-client")
                .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
                .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT").scopes("read", "write", "trust")
                .secret("$2a$10$eWlbrvrS4fDEYvgI8OoVNeCGES9VWdBG0/Zf37VLjxQOilL62iLCy")
               // .secret("$2a$10$lh4BwgE6g68inGLDC9XEhOuHCLGzUZniwGMwjsNi34naF/bmi42YC")
                .accessTokenValiditySeconds(21600).// 6小时
                refreshTokenValiditySeconds(604800);// 7天
    }


    /**
     * 认证服务器Endpoints配置
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
//        //如果需要使用refresh_token模式则需要注入userDetailService
//        endpoints.userDetailsService(userDetailsService);
//        endpoints.authenticationManager(this.authenticationManager);
//        endpoints.tokenStore(tokenStore());
//        if (jwtAccessTokenConverter != null && jwtTokenEnhancer != null) {
//            TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
//            List<TokenEnhancer> enhancerList = new ArrayList();
//            enhancerList.add(jwtTokenEnhancer);
//            enhancerList.add(jwtAccessTokenConverter);
//            tokenEnhancerChain.setTokenEnhancers(enhancerList);
//            endpoints.tokenEnhancer(tokenEnhancerChain)
//                    .accessTokenConverter(jwtAccessTokenConverter);
//        }
        endpoints.tokenStore(tokenStore()).tokenEnhancer(new UserTokenEnhancer())
                .authenticationManager(authenticationManager);
        endpoints.userDetailsService(userDetailsService);
        endpoints.exceptionTranslator(new Auth2ResponseExceptionTranslator());
    }


    /**
     * 认证服务器相关接口权限管理
     * @param security
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.authenticationEntryPoint(new CustomAuthenticationEntryPoint()); //匿名用户访问无权限资源时的异常
        security.allowFormAuthenticationForClients() //如果使用表单认证则需要加上
                .tokenKeyAccess("permitAll()");
               // .checkTokenAccess("isAuthenticated()");
    }
}
